package com.wy.controller;

import com.wy.util.Md5;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@RequestMapping("upload")
@RestController
@Slf4j
@CrossOrigin("*")
public class UploadController {
    // 就定义一下文件名称为 文件
    private static final String UPLOAD_DIR = "D:\\file\\upload\\";
    // 文件的 md5值为key，文件的大小为 value
    private static final Map<String, Long> fileSizeMap = new HashMap<>();
    private static final Map<String, FileMergeBean> mergeFileInfos = new HashMap<>();

    // 接口用于接收分片文件
    @PostMapping("/chunk")
    public String uploadChunk(@RequestParam("file") MultipartFile file,
                              @RequestParam("chunkNumber") int chunkNumber,
                              @RequestParam("totalChunks") int totalChunks,
                              @RequestParam("fileName") String fileName,
                              @RequestParam("fileMd5") String fileMd5) {
        File uploadDir = new File(UPLOAD_DIR + fileMd5);
        if (!uploadDir.exists()) {
            uploadDir.mkdirs();
            log.info("目录创建成功: {}", UPLOAD_DIR + fileMd5);
        }

        File destFile = new File(UPLOAD_DIR + fileMd5 + "\\" + "file.part" + chunkNumber);
        try {
            file.transferTo(destFile);
            return "Chunk uploaded successfully";
        } catch (IOException e) {
            e.printStackTrace();
            return "Error uploading chunk";
        }
    }

    // 文件合并接口
    @PostMapping("/merge")
    public String mergeChunks(@RequestParam("fileName") String fileName,
                              @RequestParam("totalChunks") int totalChunks,
                              @RequestParam("fileMd5") String fileMd5) {
        Path mergedFilePath = Paths.get(UPLOAD_DIR, fileMd5, "file");
        try (FileChannel fos = FileChannel.open(mergedFilePath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
            for (int i = 1; i <= totalChunks; i++) {
                Path chunkFilePath = Paths.get(UPLOAD_DIR, fileMd5, "file.part" + i);
                if (Files.exists(chunkFilePath)) {
                    try (FileChannel fis = FileChannel.open(chunkFilePath, StandardOpenOption.READ)) {
                        fis.transferTo(0, fis.size(), fos);
                    }
                    Files.delete(chunkFilePath);
                }
            }
            // 之后计算一下合并之后的文件和 当前的文件的md5值是否相同，
            String calculatedMd5 = Md5.calculateMD5(mergedFilePath.toFile());
            if (calculatedMd5.equals(fileMd5)) {
                return "File merged successfully";
            } else {
                return "MD5 mismatch after merging";
            }
        } catch (IOException e) {
            e.printStackTrace();
            return "Error merging chunks";
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
    // 检查文件是否存在，如果存在，就实现秒传， 如果不存在，就告诉前端，进而实现之后的分段上传，
    @PostMapping("/check")
    public String checkFile(@RequestParam("fileSize") long fileSize,
                            @RequestParam("fileMd5") String md5,
                            @RequestParam("fileName") String fileName) {
        // 首先比较文件的md5数值
        // 不需要比较文件的名称，再比较一下文件的大小就行了。
        if (mergeFileInfos.containsKey(md5) && mergeFileInfos.get(md5).getFileSize() == fileSize) {
            // 执行一些数据库操作。 说明
            FileMergeBean fileMergeBean = mergeFileInfos.get(md5);
            Map<String, String> userInfos = fileMergeBean.getUserInfos();
            String userId = UUID.randomUUID().toString();
            userInfos.put(userId, fileName);
            return "1";
        } else {
            FileMergeBean fileMergeBean = new FileMergeBean();
            fileMergeBean.setFileMd5(md5);
            fileMergeBean.setFileSize(fileSize);
            HashMap<String, String> userInfos = new HashMap<>();
            userInfos.put(UUID.randomUUID().toString(), fileName);
            fileMergeBean.setUserInfos(userInfos);
            mergeFileInfos.put(md5, fileMergeBean);
            return "0";
        }
    }

    @GetMapping("/download/{fileName}")
    public byte[] downloadFile(@PathVariable String fileName) throws IOException {
        File file = new File(UPLOAD_DIR + fileName);
        return FileUtils.readFileToByteArray(file);
    }
}
